package com.wei.czz.framework.store.manager;

import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.dto.common.NameValue;
import com.wei.czz.common.dto.store.assign.*;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.common.dict.DictEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.enums.store.StoreAssignTypeEnum;
import com.wei.czz.common.enums.store.StoreStatusEnum;
import com.wei.czz.common.enums.store.StoreSubmitTypeEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.store.AssignStoreListPo;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.utils.TimeUtils;
import com.wei.czz.common.vo.store.assign.AssignFormVo;
import com.wei.czz.common.vo.store.assign.AssignParamVo;
import com.wei.czz.common.vo.store.assign.AssignVo;
import com.wei.czz.framework.common.entity.DictEntity;
import com.wei.czz.framework.admin.entity.UserEntity;
import com.wei.czz.framework.admin.service.UserRoleService;
import com.wei.czz.framework.admin.service.UserService;
import com.wei.czz.framework.common.wrapper.DictWrapper;
import com.wei.czz.framework.store.entity.*;
import com.wei.czz.framework.store.service.*;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-12-03 11:00:08
 * className: AssignManager
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class AssignManager {

    private static final Logger log = LoggerFactory.getLogger(AssignManager.class);

    private final AssignStoreService assignStoreService;

    private final AssignStoreFlowService assignStoreFlowService;

    private final AuditStoreService auditStoreService;

    private final UserService userService;

    private final StoreService storeService;

    private final StoreAccountService storeAccountService;

    private final StoreBossService storeBossService;

    private final UserRoleService userRoleService;

    private final RedissonClient redissonClient;

    private final DictWrapper dictWrapper;

    public PageDto<AssignListDto> getMyAssignStorePageList(AssignFormVo assignFormVo) {
        Long optUserId = SecurityUtils.getUserId();
        assignFormVo.setUserId(optUserId);

        /*
           分页获取用户被分单商店
         */
        PageDto<AssignStoreListPo> pageDto = assignStoreService.getAssignStorePageList(assignFormVo);
        if (pageDto.isEmpty()) {
            log.info("用户被分单商店分页结果为空。userId={}", optUserId);
            return pageDto.rebuild();
        }

        List<AssignStoreListPo> storeList = pageDto.getList();

        Set<Long> userIdSet = new HashSet<>();
        List<Long> submitBusinessIdList = new ArrayList<>();
        List<Long> modifyBusinessIdList = new ArrayList<>();
        for (AssignStoreListPo assignStoreListPo : storeList) {
            userIdSet.add(assignStoreListPo.getUserId());
            if (StoreStatusEnum.SUBMIT.getValue().equals(assignStoreListPo.getStatus())) {
                submitBusinessIdList.add(assignStoreListPo.getBusinessId());
            } else if (StoreStatusEnum.MODIFY.getValue().equals(assignStoreListPo.getStatus())) {
                modifyBusinessIdList.add(assignStoreListPo.getBusinessId());
            }
        }

        /*
            查询用户名称
         */
        Map<Long, String> userNameMap = userService.getNameMap(userIdSet, Function.identity());

        /*
            获取商店提交次数和修改次数
         */
        Map<Long, Integer> storeStatMap = this.getStoreOptionStat(submitBusinessIdList, modifyBusinessIdList);

        List<AssignListDto> assignListDtoList = storeList.stream()
                .map(assignStoreListPo -> this.mapAssignListDto(assignStoreListPo, userNameMap, storeStatMap))
                .collect(Collectors.toList());
        // 封装返回
        return pageDto.rebuild(assignListDtoList);
    }

    public PageDto<AssignManageListDto> getAssignableStorePageList(AssignFormVo assignFormVo) {

        /*
           分页获取可以审核分单商店
         */
        PageDto<AssignStoreListPo> pageDto = assignStoreService.getAssignableStorePageList(assignFormVo);
        if (pageDto.isEmpty()) {
            log.info("未被分单商店分页结果为空");
            return pageDto.rebuild();
        }

        List<AssignStoreListPo> storeList = pageDto.getList();

        Set<Long> userIdSet = new HashSet<>();
        List<Long> submitBusinessIdList = new ArrayList<>();
        List<Long> modifyBusinessIdList = new ArrayList<>();
        for (AssignStoreListPo store : storeList) {
            userIdSet.add(store.getUserId());
            userIdSet.add(store.getAuditUser());
            if (StoreStatusEnum.SUBMIT.getValue().equals(store.getStatus())) {
                submitBusinessIdList.add(store.getBusinessId());
            } else if (StoreStatusEnum.MODIFY.getValue().equals(store.getStatus())) {
                modifyBusinessIdList.add(store.getBusinessId());
            }
        }

        /*
            查询用户名称
         */
        Map<Long, String> userNameMap = userService.getNameMap(userIdSet, Function.identity());

        /*
            获取商店提交次数和修改次数
         */
        Map<Long, Integer> storeStatMap = this.getStoreOptionStat(submitBusinessIdList, modifyBusinessIdList);

        List<AssignManageListDto> assignListDtoList = storeList.stream()
                .map(store -> this.mapAssignManageListDto(store, userNameMap, storeStatMap))
                .collect(Collectors.toList());
        // 封装返回
        return pageDto.rebuild(assignListDtoList);
    }

    public PageDto<AssignListDto> getNotAssignStorePageList(AssignFormVo assignFormVo) {
        // 用户主键设置成 -1 用于查询未被分单商店
        assignFormVo.setUserId(CommonEnum.MINUS_ONE.getLongValue());

        /*
           分页获取未被分单商店
         */
        PageDto<AssignStoreListPo> pageDto = assignStoreService.getAssignStorePageList(assignFormVo);
        if (pageDto.isEmpty()) {
            log.info("未被分单商店分页结果为空");
            return pageDto.rebuild();
        }

        List<AssignStoreListPo> storeList = pageDto.getList();
        // 收集用户主键
        Set<Long> userIdSet = storeList.stream().map(AssignStoreListPo::getUserId).collect(Collectors.toSet());

        /*
            查询用户名称
         */
        Map<Long, String> userNameMap = userService.getNameMap(userIdSet, Function.identity());

        List<AssignListDto> assignListDtoList = storeList.stream()
                .map(store -> this.mapAssignListDto(store, userNameMap, Collections.emptyMap()))
                .collect(Collectors.toList());
        // 封装返回
        return pageDto.rebuild(assignListDtoList);
    }

    public List<NameValue<String>> getNotAssignStoreUserList() {

        /*
            获取未被分单商店列表
         */
        List<StoreEntity> storeList = assignStoreService.getUserAssignStoreList(CommonEnum.MINUS_ONE.getLongValue());
        if (storeList.isEmpty()) {
            return Collections.emptyList();
        }

        /*
            获取用户名称
         */
        Set<Long> userIdSet = storeList.stream().map(StoreEntity::getUserId).collect(Collectors.toSet());
        Map<Long, String> userNameMap = userService.getNameMap(userIdSet, Function.identity());

        return storeList.stream()
                .map(store -> new NameValue<>(userNameMap.get(store.getUserId()), store.getUserId().toString()))
                .collect(Collectors.toList());
    }

    public List<AssignFlowListDto> getAssignStoreFlowList(Long storeId, Long masterId) {
        /*
            获取商店分单记录列表
         */
        List<AssignStoreFlowEntity> assignStoreFlowList = assignStoreFlowService.getAssignStoreFlowList(storeId,
                masterId);
        if (assignStoreFlowList.isEmpty()) {
            return Collections.emptyList();
        }

        // 收集用户主键
        Set<Long> userIdSet = assignStoreFlowList.stream()
                .map(AssignStoreFlowEntity::getUserId)
                .collect(Collectors.toSet());
        /*
            获取用户名称
         */
        Map<Long, String> userNameMap = userService.getNameMap(userIdSet, Function.identity());

        /*
            封装
         */
        return assignStoreFlowList.stream()
                .sorted(Comparator.comparing(AssignStoreFlowEntity::getId).reversed())
                .map(assignStoreFlow -> {
                    AssignFlowListDto assignFlowListDto = new AssignFlowListDto();
                    assignFlowListDto.setId(assignStoreFlow.getId().toString())
                            .setAssignTime(assignStoreFlow.getCreateTime())
                            .setSubmitType(assignStoreFlow.getSubmitType())
                            .setSubmitTypeName(StoreSubmitTypeEnum.getName(assignStoreFlow.getSubmitType()))
                            .setAssignType(assignStoreFlow.getAssignType())
                            .setAssignTypeName(StoreAssignTypeEnum.getName(assignStoreFlow.getAssignType()))
                            .setAuditUserName(userNameMap.get(assignStoreFlow.getUserId()))
                            .setCreateUserName(assignStoreFlow.getCreateUser());
                    return assignFlowListDto;
                })
                .collect(Collectors.toList());
    }

    public AssignPageEnumDto getMyAssignEnum() {
        Long optUserId = SecurityUtils.getUserId();

        /*
            获取未分单商店数量
         */
        Integer notAssignCount = assignStoreService.getUserAssignStoreCount(CommonEnum.MINUS_ONE.getLongValue());

        /*
            获取用户被分单商店关联用户
         */
        Set<Long> userIdSet = assignStoreService.getStoreUserIdSet(optUserId);
        // 获取用户列表
        List<NameValue<String>> userList = Collections.emptyList();
        if (!userIdSet.isEmpty()) {
            userList = userService.findUserList(userIdSet,
                    id -> Optional.ofNullable(id).map(Objects::toString).orElse(null));
        }

        AssignPageEnumDto assignPageEnumDto = new AssignPageEnumDto();
        assignPageEnumDto.setNotAssignCount(notAssignCount)
                .setUserList(userList)
                .setStatusList(StoreStatusEnum.getStatusEnumList());
        return assignPageEnumDto;
    }

    public AssignManageEnumDto getAssignStoreManageEnum() {

        /*
            获取用户被分单商店关联用户
         */
        Set<Long> userIdSet = assignStoreService.getStoreUserIdSet(null);
        // 获取用户列表
        List<NameValue<String>> userList = Collections.emptyList();
        if (!userIdSet.isEmpty()) {
            userList = userService.findUserList(userIdSet,
                    id -> Optional.ofNullable(id).map(Objects::toString).orElse(null));
        }

        AssignManageEnumDto assignManageEnumDto = new AssignManageEnumDto();
        assignManageEnumDto.setUserList(userList)
                .setStatusList(StoreStatusEnum.getStatusEnumList())
                .setAssignTypeList(StoreAssignTypeEnum.getAssignTypeList())
                .setAuditUserList(this.getAuditUserList());
        return assignManageEnumDto;
    }

    @Transactional
    public String claimStore(AssignVo assignVo) {

        List<AssignParamVo> assignParamVoList = assignVo.getStoreVoList();

        AssignParamVo assignParamVo = assignParamVoList.get(0);
        if (Objects.isNull(assignParamVo.getStoreId())) {
            log.info("商店列表存储的商店主键为空。{}", assignParamVo);
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "商店主键不能为空");
        }

        String lockKey = RedisConstant.LOCK_STORE_KEY + assignParamVo.getStoreId();
        RLock lock = redissonClient.getLock(lockKey);
        boolean bool = lock.tryLock();
        log.info("用户审核认领商店，尝试加锁完成。lockKey={} bool={}", lockKey, bool);
        if (!bool) {
            throw new CzzException(ResultEnum.REFRESH.getCode(), "您认领的商店正在被操作中，认领失败");
        }
        try {
            /*
                判断商店是否可以分单
             */
            String tipMessage = this.checkAssignStore(assignParamVoList);
            if (StringUtils.isNotEmpty(tipMessage)) {
                // 提示消息不为空，直接返回
                return tipMessage;
            }

            assignVo.setUserId(SecurityUtils.getUserId());
            assignVo.setAssignType(StoreAssignTypeEnum.CLAIM.getValue());

            /*
                商店分单
             */
            assignStoreService.assignStore(assignVo);

            /*
                保存商店分单记录
             */
            assignStoreFlowService.saveAssignStoreFlow(assignVo);

            // 正常返回
            return null;
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Transactional
    public String assignStore(AssignVo assignVo) {

        List<AssignParamVo> assignParamVoList = assignVo.getStoreVoList();

        RLock lock;
        boolean isOne = assignParamVoList.size() == 1;
        if (isOne) {
            lock = redissonClient.getLock(RedisConstant.LOCK_STORE_KEY + assignParamVoList.get(0).getStoreId());
        } else {
            RLock[] locks = assignParamVoList.stream()
                    .map(AssignParamVo::getStoreId)
                    .map(id -> redissonClient.getLock(RedisConstant.LOCK_STORE_KEY + id))
                    .toArray(RLock[]::new);
            // 获取批量锁对象
            lock = redissonClient.getMultiLock(locks);
        }
        try {
            // 尝试加锁
            boolean bool = lock.tryLock(3, 30, TimeUnit.SECONDS);
            log.info("商店审核分单，尝试加锁完成。isOne={} lockKey={} bool={}", isOne,
                    isOne ? lock.getName() : assignParamVoList, bool);
            if (!bool) {
                return "您分单的商店正在被操作中，分单失败";
            }
        } catch (InterruptedException e) {
            log.error("商店分单尝试加锁中断异常。message={}", e.getMessage(), e);
            throw new CzzException();
        }
        try {
            /*
                判断商店是否可以分单
             */
            String tipMessage = this.checkAssignStore(assignParamVoList);
            if (StringUtils.isNotEmpty(tipMessage)) {
                // 提示消息不为空，直接返回
                return tipMessage;
            }

            assignVo.setAssignType(StoreAssignTypeEnum.ASSIGN.getValue());

            /*
                商店分单
             */
            assignStoreService.assignStore(assignVo);
            /*
                保存商店分单记录
             */
            assignStoreFlowService.saveAssignStoreFlow(assignVo);

            return null;
        } finally {
            if (isOne) {
                if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            } else {
                lock.unlock();
            }
        }
    }

    /**
     * 商店分单映射
     * @param assignStoreListPo 商店对象
     * @param userNameMap       用户名称映射
     * @param storeStatMap      商店提交/修改次数映射
     * @return 映射结果
     */
    private AssignListDto mapAssignListDto(AssignStoreListPo assignStoreListPo, Map<Long, String> userNameMap,
                                           Map<Long, Integer> storeStatMap) {
        AssignListDto assignListDto = new AssignListDto();
        assignListDto.setId(assignStoreListPo.getId().toString())
                .setStoreId(assignStoreListPo.getStoreId().toString())
                .setName(assignStoreListPo.getName())
                .setUserName(userNameMap.get(assignStoreListPo.getUserId()))
                .setStatus(assignStoreListPo.getStatus())
                .setStatusName(StoreStatusEnum.getName(assignStoreListPo.getStatus()))
                .setSubmitType(assignStoreListPo.getSubmitType())
                .setSubmitTypeName(StoreSubmitTypeEnum.getName(assignStoreListPo.getSubmitType()))
                .setSubmitCount(storeStatMap.getOrDefault(assignStoreListPo.getBusinessId(), 0))
                .setSubmitTime(assignStoreListPo.getCreateTime());
        return assignListDto;
    }

    /**
     * 获取商店提交次数和修改次数映射
     * @param submitBusinessIdList 提交业务主键列表
     * @param modifyBusinessIdList 修改业务主键列表
     * @return 映射结果
     */
    private Map<Long, Integer> getStoreOptionStat(List<Long> submitBusinessIdList, List<Long> modifyBusinessIdList) {
        /*
            获取商店提交次数和修改次数
         */
        List<StoreEntity> storeOptionStatPoList = storeService.getStoreOptionStatList(submitBusinessIdList,
                modifyBusinessIdList);
        Map<Long, Integer> storeStatMap = Collections.emptyMap();
        if (!storeOptionStatPoList.isEmpty()) {
            Map<Long, Long> storeFinishMap;
            if (modifyBusinessIdList.isEmpty()) {
                storeFinishMap = Collections.emptyMap();
            } else {
                /*
                    获取商店最新审核通过主键
                 */
                List<StoreEntity> storeFinishList = storeService.getStoreMaxFinishList(modifyBusinessIdList);
                storeFinishMap = storeFinishList.stream().collect(
                        Collectors.toMap(StoreEntity::getBusinessId, StoreEntity::getId)
                );
            }
            storeStatMap = storeOptionStatPoList.stream()
                    .filter(store -> {
                        Long id = storeFinishMap.get(store.getBusinessId());
                        if (Objects.isNull(id)) {
                            /*
                                根据业务主键判断 提交 和 修改
                                为空则是 提交
                             */
                            return true;
                        }
                        // 过滤掉最新‘审核通过’前的所有’修改退回‘状态数据
                        return store.getId().compareTo(id) > 0;
                    })
                    .collect(Collectors.groupingBy(
                            StoreEntity::getBusinessId,
                            Collectors.reducing(0, s -> 1, Integer::sum)
                    ));
        }
        return storeStatMap;
    }

    /**
     * 可以分单商店映射
     * @param assignStoreListPo 商店分单对象
     * @param userNameMap       用户名称映射
     * @param storeStatMap      商店提交/修改次数映射
     * @return 映射结果
     */
    private AssignManageListDto mapAssignManageListDto(AssignStoreListPo assignStoreListPo,
                                                       Map<Long, String> userNameMap,
                                                       Map<Long, Integer> storeStatMap) {
        AssignManageListDto assignManageListDto = new AssignManageListDto();
        assignManageListDto.setId(assignStoreListPo.getId().toString())
                .setStoreId(assignStoreListPo.getStoreId().toString())
                .setName(assignStoreListPo.getName())
                .setUserName(userNameMap.get(assignStoreListPo.getUserId()))
                .setStatus(assignStoreListPo.getStatus())
                .setStatusName(StoreStatusEnum.getName(assignStoreListPo.getStatus()))
                .setSubmitCount(storeStatMap.getOrDefault(assignStoreListPo.getBusinessId(), 0))
                .setSubmitTime(assignStoreListPo.getCreateTime())
                .setAuditUser(CommonEnum.filterDefault(assignStoreListPo.getAuditUser(), Objects::toString))
                .setAuditUserName(userNameMap.get(assignStoreListPo.getAuditUser()))
                .setAssignTime(assignStoreListPo.getUpdateTime())
                .setSubmitType(assignStoreListPo.getSubmitType())
                .setSubmitTypeName(StoreSubmitTypeEnum.getName(assignStoreListPo.getSubmitType()))
                .setAssignType(assignStoreListPo.getAssignType())
                .setAssignTypeName(StoreAssignTypeEnum.getName(assignStoreListPo.getAssignType()));
        return assignManageListDto;
    }

    /**
     * 校验商店是否可以分单/审核操作
     * @param assignParamVoList 商店参数列表
     * @return 提示消息
     */
    private String checkAssignStore(List<AssignParamVo> assignParamVoList) {
        List<Long> storeIdList = new ArrayList<>();
        List<Long> assignAccountList = new ArrayList<>();
        List<Long> assignBossList = new ArrayList<>();

        for (AssignParamVo assignParamVo : assignParamVoList) {
            if (StoreSubmitTypeEnum.SUBMIT_STORE.getValue().equals(assignParamVo.getSubmitType())
                    || StoreSubmitTypeEnum.STORE_MODIFY.getValue().equals(assignParamVo.getSubmitType())) {
                storeIdList.add(assignParamVo.getStoreId());
            } else if (StoreSubmitTypeEnum.ADD_STORE_ACCOUNT.getValue().equals(assignParamVo.getSubmitType())
                    || StoreSubmitTypeEnum.STORE_ACCOUNT_MODIFY.getValue().equals(assignParamVo.getSubmitType())) {
                assignAccountList.add(assignParamVo.getStoreId());
            } else if (StoreSubmitTypeEnum.ADD_STORE_BOSS.getValue().equals(assignParamVo.getSubmitType())
                    || StoreSubmitTypeEnum.STORE_BOSS_MODIFY.getValue().equals(assignParamVo.getSubmitType())) {
                assignBossList.add(assignParamVo.getStoreId());
            }
        }

        if (!storeIdList.isEmpty()) {
            /*
                校验商店
             */
            log.info("校验商店。storeIdList={}", storeIdList);
            List<StoreEntity> storeList = storeService.getStoreList(storeIdList, null);
            for (StoreEntity store : storeList) {
                /*
                    判断是否存在已删除商店
                 */
                if (CommonEnum.ONE.getValue().equals(store.getDeleteStatus())) {
                    log.info("商店已被删除。id={} name={}", store.getId(), store.getName());
                    return String.format("您操作的【%s】商店已删除，请重新操作", store.getName());
                }
                if (StoreStatusEnum.AUDIT_RETURN.getValue().equals(store.getStatus())) {
                    log.info("商店已被审核退回。id={} name={}", store.getId(), store.getName());
                    return String.format("您操作的【%s】商店被审核退回，请重新操作", store.getName());
                }
                if (StoreStatusEnum.MODIFY_RETURN.getValue().equals(store.getStatus())) {
                    log.info("商店已被审核退回修改。id={} name={}", store.getId(), store.getName());
                    return String.format("您操作的【%s】商店被审核退回修改，请重新操作", store.getName());
                }
                if (StoreStatusEnum.FINISH.getValue().equals(store.getStatus())) {
                    log.info("商店已被审核通过。id={} name={}", store.getId(), store.getName());
                    return String.format("您操作的【%s】商店已审核通过，请重新操作", store.getName());
                }
            }
        }
        if (!assignAccountList.isEmpty()) {
            /*
                校验商店账户
             */
            log.info("校验商店账户。storeIdList={}", assignAccountList);
            List<StoreAccountEntity> storeAccountList =
                    storeAccountService.batchGetStoreAuditAccount(assignAccountList, null);
            if (storeAccountList.isEmpty()) {
                return "待审核商店账户已消失，请重新操作";
            }
            for (StoreAccountEntity storeAccount : storeAccountList) {
                if (CommonEnum.ONE.getValue().equals(storeAccount.getDeleteStatus())) {
                    log.info("商店账户已被删除。id={} name={}", storeAccount.getId(), storeAccount.getName());
                    return String.format("您操作的【%s】商店账户已删除，请重新操作", storeAccount.getName());
                }
                if (CommonEnum.ONE.getValue().equals(storeAccount.getAuditStatus())) {
                    log.info("商店账户已被审核通过。id={} name={}", storeAccount.getId(), storeAccount.getName());
                    return String.format("您操作的【%s】商店账户已审核通过，请重新操作", storeAccount.getName());
                }
                if (CommonEnum.TWO.getValue().equals(storeAccount.getAuditStatus())) {
                    log.info("商店账户已被审核拒绝。id={} name={}", storeAccount.getId(), storeAccount.getName());
                    return String.format("您操作的【%s】商店账户已审核拒绝，请重新操作", storeAccount.getName());
                }
            }
        }
        if (!assignBossList.isEmpty()) {
            /*
                校验商店老板
             */
            log.info("校验商店老板。storeIdList={}", assignAccountList);
            List<StoreBossEntity> storeBossList = storeBossService.batchGetStoreAuditBoss(assignBossList,
                    null);
            if (storeBossList.isEmpty()) {
                return "待审核商店老板已消失，请重新操作";
            }
            for (StoreBossEntity storeBoss : storeBossList) {
                if (CommonEnum.ONE.getValue().equals(storeBoss.getDeleteStatus())) {
                    log.info("商店老板已被删除。id={} name={}", storeBoss.getId(), storeBoss.getName());
                    return String.format("您操作的【%s】商店老板已删除，请重新操作", storeBoss.getName());
                }
                if (CommonEnum.ONE.getValue().equals(storeBoss.getAuditStatus())) {
                    log.info("商店老板已被审核通过。id={} name={}", storeBoss.getId(), storeBoss.getName());
                    return String.format("您操作的【%s】商店老板已审核通过，请重新操作", storeBoss.getName());
                }
                if (CommonEnum.TWO.getValue().equals(storeBoss.getAuditStatus())) {
                    log.info("商店老板已被审核拒绝。id={} name={}", storeBoss.getId(), storeBoss.getName());
                    return String.format("您操作的【%s】商店老板已审核拒绝，请重新操作", storeBoss.getName());
                }
            }
        }
        // 没有问题，正常返回
        return null;
    }

    /**
     * 获取审核员用户列表操作
     * @return 审核员用户列表
     */
    private List<UserAuditStoreStatDto> getAuditUserList() {
        Date[] currentMonthDates = TimeUtils.getCurrentMonthDates();
        Date[] currentDates = TimeUtils.getCurrentDates();

        /*
            获取字典配置
         */
        DictEntity dict = dictWrapper.getOneDict(DictEnum.STORE_AUDIT_ROLE);
        long roleId;
        try {
            roleId = Long.parseLong(dict.getValue());
        } catch (NumberFormatException e) {
            throw new CzzException(String.format("【%s】配置错误，值不是数字", DictEnum.STORE_AUDIT_ROLE.getName()));
        }

        /*
            获取商店审核员用户列表
         */
        List<UserEntity> auditUserList = userRoleService.getUserList(roleId);
        // 收集用户主键
        List<Long> userIdList = auditUserList.stream().map(UserEntity::getUserId).collect(Collectors.toList());

        // 用户关联的商店分单
        List<AssignStoreEntity> assignStoreList = assignStoreService.getassignStoreList(userIdList);
        // 用户关联的商店审核记录
        List<AuditStoreEntity> auditStoreList = auditStoreService.getAuditStoreList(userIdList, currentMonthDates[0]);

        Map<Long, Integer> assignStoreMap = assignStoreList.stream().collect(
                Collectors.groupingBy(AssignStoreEntity::getUserId, Collectors.reducing(0, v -> 1, Integer::sum))
        );

        Map<Long, Map<String, Integer>> auditStoreMap = auditStoreList.stream()
                .flatMap(auditStore -> {
                    Date createTime = auditStore.getCreateTime();
                    NameValue<Long> nameValue = null;
                    if (createTime.after(currentDates[0]) && createTime.before(currentDates[1])) {
                        nameValue = new NameValue<>("0", auditStore.getUserId());
                    }
                    NameValue<Long> nameValue2 = null;
                    if (createTime.after(currentMonthDates[0]) && createTime.before(currentMonthDates[1])) {
                        nameValue2 = new NameValue<>("1", auditStore.getUserId());
                    }
                    return Stream.of(nameValue, nameValue2);
                })
                .filter(Objects::nonNull)
                .collect(Collectors.groupingBy(
                        NameValue::getValue,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                nameValues -> nameValues.stream()
                                        .collect(Collectors.groupingBy(
                                                NameValue::getName,
                                                Collectors.reducing(0, v -> 1, Integer::sum)
                                        ))
                        )
                ));

        return auditUserList.stream()
                .map(auditUser -> {
                    Map<String, Integer> statMap = auditStoreMap.getOrDefault(auditUser.getUserId(),
                            Collections.emptyMap());

                    UserAuditStoreStatDto userAuditStoreStatDto = new UserAuditStoreStatDto();
                    userAuditStoreStatDto.setUserId(auditUser.getUserId().toString())
                            .setUserName(auditUser.getUsername())
                            .setWaitAuditCount(assignStoreMap.getOrDefault(auditUser.getUserId(), 0))
                            .setDayAuditCount(statMap.getOrDefault("0", 0))
                            .setMonthAuditCount(statMap.getOrDefault("1", 0))
                    ;
                    return userAuditStoreStatDto;
                })
                .collect(Collectors.toList());
    }

}
